package validate

import (
	"context"
	"gitee.com/bobo-rs/idea-space-framework/framework/model"
	"gitee.com/bobo-rs/idea-space-framework/framework/service"
	"gitee.com/bobo-rs/idea-space-framework/pkg/utils"
	"github.com/gogf/gf/v2/errors/gerror"
	"github.com/gogf/gf/v2/util/gconv"
	"github.com/gogf/gf/v2/util/gvalid"
)

// RuleRegisterConfig 注册配置规则
func RuleRegisterConfig() {
	gvalid.RegisterRuleByMap(map[string]gvalid.RuleFunc{
		`config-group-exists-id`: RuleConfigGroupExistsById,
		`group-name-uni`:         RuleConfigGroupUniByGroupName,
		`config-save-params`:     RuleConfigSaveParams,
	})
}

// RuleConfigGroupExistsById 通过配置组ID检测配置组是否存在
func RuleConfigGroupExistsById(ctx context.Context, in gvalid.RuleFuncInput) error {
	id := in.Value.Uint()
	if id == 0 {
		return nil
	}

	// 验证配置ID是否存在
	if !service.Config().ProcessGroupExistsById(ctx, id) {
		return gerror.New(`配置组不存在`)
	}
	return nil
}

// RuleConfigGroupUniByGroupName 通过配置组名是否唯一
func RuleConfigGroupUniByGroupName(ctx context.Context, in gvalid.RuleFuncInput) error {
	var (
		groupName = in.Value.String()
		data      = in.Data.Map()
		groupId   uint
		detail    model.ConfigGroupCategoryItem
	)

	if len(groupName) == 0 {
		return gerror.New(`缺少配置组名`)
	}
	// 配置组ID
	id, ok := data["id"]
	if !ok {
		return gerror.New(`缺少配置组ID`)
	}
	groupId = gconv.Uint(id)

	// 获取配置组名
	_ = service.Config().ProcessGroupDetailByGroupName(ctx, groupName, &detail)
	if groupId == 0 {
		// 添加配置，配置组名是否重复
		if detail.Id == 0 {
			return nil
		}
		return gerror.New(`配置组名已存在`)
	}

	// 编辑时，
	if detail.Id == 0 {
		// 已配置
		if service.Config().ProcessExistsByGroupId(ctx, groupId) {
			return gerror.New(`不允许修改配置组名`)
		}
		return nil
	}

	// 同一配置组数据编辑
	if groupId == detail.Id {
		return nil
	}

	// 不同配置组-配置组是否已经配置，已配置
	if service.Config().ProcessExistsByGroupName(ctx, groupName) {
		return gerror.Newf(`不允许修改配置组名%s`, groupName)
	}
	return nil
}

// RuleConfigSaveParams 保存系统配置参数规则
func RuleConfigSaveParams(ctx context.Context, in gvalid.RuleFuncInput) error {
	var (
		items = []model.ConfigDetailItem{}
	)
	if err := in.Value.Structs(&items); err != nil {
		return gerror.Wrapf(err, `保存配置扫描参数到ConfigSaveItem失败%s`, err.Error())
	}
	// 获取配置名
	names := utils.NewArray(items).ArrayColumnsUniqueString(`name`)
	if len(names) == 0 || (len(names) != len(items)) {
		return gerror.Newf(`缺少配置或配置名不匹配数量不匹配%d=>%d`, len(items), len(names))
	}

	// 获取配置信息-不存在则新的配置名
	detailMap, _ := service.Config().ProcessConfigDetailMapByName(ctx, names)
	for _, item := range items {
		if item.GroupId == 0 {
			return gerror.Newf(`缺少[%s]配置组ID`, item.Name)
		}
		// 配置详情-配置名存在，但不是当前配置组配置名
		detail, ok := detailMap[item.Name]
		if ok && detail.GroupId != item.GroupId {
			return gerror.Newf(`此配置名[%s]已配置到[%s]组，请保持配置名在配置组唯一`, item.Name, detail.GroupName)
		}
	}
	return nil
}
